﻿using System;
using System.Collections.Generic;
using System.Linq;
using Joel.Vishnu.Modelo.Entidades;
using Joel.Vishnu.Presentacion.Vistas;
using Joel.Vishnu.Presentacion;
using Joel.Vishnu.Modelo.Objetos;

namespace Joel.Vishnu.Consola
{
    class Facturacion : Base, IFacturacion, IGestionarFacturas
    {
        #region Constructores

        public Facturacion()
            : base()
        {
            presentadorHistorial = new FacturacionPresentador(this);
            presentadorGestion = new GestionarFacturasPresentador(this);
            listaFacturaDetalles = new List<FacturaDetalle>();
            validador = String.Empty;
        }

        #endregion

        #region Atributos

        private FacturacionPresentador presentadorHistorial;
        private GestionarFacturasPresentador presentadorGestion;
        private List<Factura> listaFacturas;


        private Int32 clienteId;
        private List<Cliente> listaClientes;
        private Int32 empleadoId;
        private List<Empleado> listaEmpleados;
        private Int32 productoId;
        private List<Producto> listaProductos;
        private Int32 cantidad;
        private List<FacturaDetalle> listaFacturaDetalles;
        private String subTotal;
        private String total;
        private String iva;
        private Int32 indiceFacturaDetalleSeleccionada;


        private Int32 facturaId;
        private String validador;

        #endregion

        #region Propiedades

        public List<Factura> ListaFacturas
        {
            set { listaFacturas = value; }
        }


        public Int32 ClienteId
        {
            get { return clienteId; }
        }

        public List<Cliente> ListaClientes
        {
            set { listaClientes = value; }
        }

        public Int32 EmpleadoId
        {
            get { return empleadoId; }
        }

        public List<Empleado> ListaEmpleados
        {
            set { listaEmpleados = value; }
        }

        public Int32 ProductoId
        {
            get { return productoId; }
        }

        public List<Producto> ListaProductos
        {
            set { listaProductos = value; }
        }

        public Int32 Cantidad
        {
            get { return cantidad; }
            set { cantidad = 0; }
        }

        public List<FacturaDetalle> ListaFacturaDetalles
        {
            get
            {
                return listaFacturaDetalles;
            }
            set
            {
                listaFacturaDetalles = value;
            }
        }

        public String SubTotal
        {
            set { subTotal = value; }
        }

        public String Total
        {
            set { total = value; }
        }

        public String Iva
        {
            get { return iva; }
            set { iva = value; }
        }

        public Int32 IndiceFacturaDetalleSeleccionada
        {
            get { return indiceFacturaDetalleSeleccionada; }
        }


        private Clientes Clientes
        {
            get { return new Clientes(); }
        }

        private Empleados Empleados
        {
            get { return new Empleados(); }
        }

        private Productos Productos
        {
            get { return new Productos(); }
        }

        #endregion

        #region Metodos

        public String Menu()
        {
            Console.Clear();
            Titulo("********** Facturación **********");
            MensajeInformativo("(1) Gestionar");
            MensajeInformativo("(2) Historial");
            Console.WriteLine();
            MensajeInformativo("(0) Menú principal");
            Console.WriteLine();
            MensajeInformativo("Presione el número de la opción deseada.");
            return Console.ReadKey().KeyChar.ToString();
        }

        public void Historial()
        {
            try
            {
                Console.Clear();
                Titulo("********** Historial **********");
                MostrarFacturasHistorial();
                Console.WriteLine();
                MensajeInformativoSeguido("Seleccione Id para ver detalles: ");
                validador = Console.ReadLine();
                if (Validadores.ValidadorEnteros(validador) == false ||
                    listaFacturas.Where(x => x.Id == Convert.ToInt32(validador)).FirstOrDefault() == null)
                    throw new Exception("Debe seleccionar alguna factura de la lista.");
                facturaId = Convert.ToInt32(validador);
                Console.WriteLine();
                Titulo(String.Format("Detalles de factura número {0}", facturaId));
                MostrarFacturaDetallesHistorial(facturaId);
            }
            catch (Exception ex)
            {
                MensajeError(ex.Message);
            }
        }

        public void Gestionar()
        {
            try
            {
                Cliente cliente = new Cliente();
                Empleado empleado = new Empleado();
                String opcion = String.Empty;
                Boolean terminar = false;
                listaFacturaDetalles.Clear();

                Console.Clear();
                Titulo("********** Gestionar factura **********");
                Clientes.MostrarClientes();
                Console.WriteLine();
                MensajeInformativoSeguido("Seleccione cliente Id: ");
                validador = Console.ReadLine();
                if (Validadores.ValidadorEnteros(validador) == false)
                    throw new Exception("Debe seleccionar un cliente.");
                clienteId = Convert.ToInt32(validador);
                presentadorGestion.ActualizarClientes();
                cliente = listaClientes.Where(x => x.Id == clienteId).FirstOrDefault();
                //TODO: Como hacer para actualizar el listado de clientes una sola vez.
                if (cliente == null)
                    throw new Exception("Debe seleccionar un cliente de la lista.");
                Console.WriteLine();
                Empleados.MostrarEmpleados();
                Console.WriteLine();
                MensajeInformativoSeguido("Seleccione empleado Id: ");
                validador = Console.ReadLine();
                if (Validadores.ValidadorEnteros(validador) == false)
                    throw new Exception("Debe seleccionar un empleado.");
                empleadoId = Convert.ToInt32(validador);
                presentadorGestion.ActualizarEmpleados();
                empleado = listaEmpleados.Where(x => x.Id == empleadoId).FirstOrDefault();
                if (empleado == null)
                    throw new Exception("Debe seleccionar un empleado de la lista.");
                MostrarFacturaDetallesGestion();
                MensajeInformativo(ArmarLinea("Subtotal: ", 10) + "$0.00");
                MensajeInformativo(ArmarLinea("IVA: ", 10) + "$0.00");
                MensajeInformativo(ArmarLinea("Total: ", 10) + "$0.00");
                Console.WriteLine();
                MensajeInformativoSeguido("(G)estionar  (A)gregar detalle  (R)emover detalle  (C)ancelar");
                opcion = Console.ReadKey().KeyChar.ToString().ToUpper();
                while (terminar == false)
                {
                    switch (opcion)
                    {
                        case "G":
                            {
                                presentadorGestion.Gestionar();
                                MensajeInformativoSeguido("Factura ingresada.");
                                Console.ReadKey();
                                terminar = true;
                                break;
                            }
                        case "A":
                            {
                                AgregarDetalle();
                                opcion = MostrarFacturaGestion(cliente, empleado);
                                break;
                            }
                        case "R":
                            {
                                RemoverDetalle();
                                opcion = MostrarFacturaGestion(cliente, empleado);
                                break;
                            }
                        case "C":
                            {
                                terminar = true;
                                break;
                            }
                        default:
                            {
                                terminar = true;
                                break;
                            }
                    }
                }
            }
            catch (Exception ex)
            {
                MensajeError(ex.Message);
            }
        }

        public void AgregarDetalle()
        {
            Console.Clear();
            Productos.MostrarProductos();
            Console.WriteLine();
            MensajeInformativoSeguido("Seleccione Id: ");
            validador = Console.ReadLine();
            if (Validadores.ValidadorEnteros(validador) == false)
                throw new Exception("El producto Id debe ser un número entero.");
            presentadorGestion.ActualizarProductos();
            if (validador == String.Empty || listaProductos.Where(x => x.Id == Convert.ToInt32(validador)).FirstOrDefault() == null)
                throw new Exception("Debe seleccionar un producto de la lista.");
            productoId = Convert.ToInt32(validador);
            MensajeInformativoSeguido("Cantidad: ");
            validador = Console.ReadLine();
            if (Validadores.ValidadorEnteros(validador) == false || Convert.ToInt32(validador) < 1 || Convert.ToInt32(validador) > 100)
                throw new Exception("La cantidad debe ser un número entre 1 y 100 inclusive.");//TODO: Rearmar la cantidad.
            cantidad = Convert.ToInt32(validador);
            presentadorGestion.AgregarDetalle();
        }

        public void RemoverDetalle()
        {
            Console.Clear();
            MensajeInformativo(String.Format("{0} {1} {2} {3} {4}",
                ArmarLineaInversa("Índice", 6),
                ArmarLinea("Producto", 12),
                ArmarLineaInversa("Precio", 7),
                ArmarLineaInversa("Cantidad", 8),
                ArmarLineaInversa("Subtotal", 8)));
            foreach (var item in listaFacturaDetalles)
                Console.WriteLine(String.Format("{0} {1} {2} {3} {4}",
                    ArmarLineaInversa(Convert.ToString(listaFacturaDetalles.IndexOf(item)), 6),
                    ArmarLinea(item.ProductoNombre, 12),
                    ArmarLineaInversa(item.PrecioConFormato, 7),
                    ArmarLineaInversa(item.CantidadConFormato, 8),
                    ArmarLineaInversa(item.SubtotalConFormato, 8)));
            Console.WriteLine();
            MensajeInformativoSeguido("Seleccione índice: ");
            validador = Console.ReadLine();
            if (Validadores.ValidadorEnteros(validador) == false
                && listaFacturaDetalles.Count > 0
                && listaFacturaDetalles.Count - 1 >= Convert.ToInt32(validador))
                throw new Exception("Debe seleccionar un índice de la lista.");
            indiceFacturaDetalleSeleccionada = Convert.ToInt32(validador);
            presentadorGestion.RemoverDetalle();
        }

        public String MostrarFacturaGestion(Cliente cliente, Empleado empleado)
        {
            Console.Clear();
            MensajeInformativo(String.Format("Cliente: {0}", cliente.ApellidoNombre));
            MensajeInformativo(String.Format("Empleado: {0}", empleado.ApellidoNombre));
            Console.WriteLine();
            MostrarFacturaDetallesGestion();
            Console.WriteLine();
            MensajeInformativo(ArmarLinea("Subtotal: ", 10) + ArmarLineaInversa(subTotal, 10));
            MensajeInformativo(ArmarLinea("IVA: ", 10) + ArmarLineaInversa(iva, 10));
            MensajeInformativo(ArmarLinea("Total: ", 10) + ArmarLineaInversa(total, 10));
            Console.WriteLine();
            MensajeInformativo("(G)estionar  (A)gregar detalle  (R)emover detalle  (C)ancelar");
            return Console.ReadKey().KeyChar.ToString().ToUpper();
        }

        public void MostrarFacturasHistorial()
        {
            MensajeInformativo(String.Format("{0} {1} {2} {3} {4} {5} {6}",
                ArmarLineaInversa("Id", 3),
                ArmarLinea("Cliente", 25),
                ArmarLinea("Empleado", 25),
                ArmarLinea("Fecha y hora", 22),
                ArmarLineaInversa("Subtotal", 10),
                ArmarLineaInversa("Iva", 7),
                ArmarLineaInversa("Total", 11)));
            presentadorHistorial.ActualizarFacturas();
            foreach (var item in listaFacturas)
                Console.WriteLine(String.Format("{0} {1} {2} {3} {4} {5} {6}",
                    ArmarLineaInversa(Convert.ToString(item.Id), 3),
                    ArmarLinea(item.ClienteApellidoNombre, 25),
                    ArmarLinea(item.EmpleadoApellidoNombre, 25),
                    ArmarLinea(Convert.ToString(item.FechaHora), 22),
                    ArmarLineaInversa(item.SubtotalConFormato, 10),
                    ArmarLineaInversa(item.IvaConFormato, 7),
                    ArmarLineaInversa(item.TotalConFormato, 11)));
        }

        public void MostrarFacturaDetallesHistorial(Int32 facturaId)
        {
            MensajeInformativo(String.Format("{0} {1} {2} {3}",
                //ArmarLineaInversa("Id", 3),
                            ArmarLinea("Producto", 12),
                            ArmarLineaInversa("Precio", 6),
                            ArmarLineaInversa("Cantidad", 8),
                            ArmarLineaInversa("Subtotal", 10)));
            Factura factura = listaFacturas.Where(x => x.Id == facturaId).FirstOrDefault();
            //foreach (var factura in listaFacturas)
            //{
            //    if (factura.Id == facturaId)
            //    {
            foreach (var detalle in factura.Detalles)
            {
                presentadorHistorial.ActualizarFacturas();
                Console.WriteLine(String.Format("{0} {1} {2} {3}",
                    //ArmarLineaInversa(Convert.ToString(detalle.Id), 3),
                    ArmarLinea(detalle.Producto.Nombre, 12),
                    ArmarLineaInversa(detalle.PrecioConFormato, 6),
                    ArmarLineaInversa(detalle.CantidadConFormato, 8),
                    ArmarLineaInversa(detalle.SubtotalConFormato, 10)));
                //    }
                //}
            }
            Console.ReadKey();
        }

        public void MostrarFacturaDetallesGestion()
        {
            Console.WriteLine();
            MensajeInformativo(String.Format("{0} {1} {2} {3}",
                            ArmarLinea("Producto", 15),
                            ArmarLineaInversa("Precio", 8),
                            ArmarLineaInversa("Cantidad", 8),
                            ArmarLineaInversa("Subtotal", 10)));
            if (listaFacturaDetalles.Count != 0)
            {
                foreach (var detalle in listaFacturaDetalles)
                {
                    presentadorHistorial.ActualizarFacturas();
                    Console.WriteLine(String.Format("{0} {1} {2} {3}",
                        ArmarLinea(detalle.Producto.Nombre, 15),
                        ArmarLineaInversa(detalle.PrecioConFormato, 8),
                        ArmarLineaInversa(detalle.CantidadConFormato, 8),
                        ArmarLineaInversa(detalle.SubtotalConFormato, 10)));
                }
            }
            Console.WriteLine();
        }

        #endregion
    }
}
